﻿#include <sstream>
#include <CXXLCOMPOSITE.HPP>
#include <CXXLXMLCOMPOSITE.HPP>
#include <TXTSTORAGE.HPP>

using namespace std;
using namespace CxxlMan;

#define COMPOSITETXTDATA cxxlComposite<string_wrapper<wchar_t>,false>

/*******************************************************************
** 實作 cxxlComposite::Composite_Export()，把子 cxxlComposite 節點
** 中，只存放永續資料的節點和不包含永續資料的子節點(只包含有孫節點)
** 分開，以便 centralizedmgr 的再生功能使用
*******************************************************************/

class ITxt_attrComposite_Export
{
public:
    virtual void TxtAttrComposite_Export(COMPOSITETXTDATA *Node) = 0;
};

class Txt_attrComposite:public COMPOSITETXTDATA
{

  virtual void cxxlFASTCALL Composite_Export(void *def, COMPOSITETXTDATA *Node) const
  {
    ((ITxt_attrComposite_Export *)def)->TxtAttrComposite_Export(Node);
  }

  virtual COMPOSITETXTDATA * cxxlFASTCALL CreateSelf(UNICODE_String idName,ISpirit *spirit) const
  {
    return new Txt_attrComposite(idName,spirit);
  }

public:
  Txt_attrComposite(const UNICODE_String &idName, ISpirit *spirit)
    :cxxlObject(spirit),
    COMPOSITETXTDATA(idName, spirit)
  {
  }

  virtual ~Txt_attrComposite()
  {
  }
};

class CTxt_attrComposite_Export:virtual public cxxlObject, public ITxt_attrComposite_Export
{
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > SubNode_List;
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Attr_List;

  virtual void TxtAttrComposite_Export(COMPOSITETXTDATA *Node)
  {
    if(Node->GetName() == SETCOUNT)
      SubNode_List->Push_Front(Node);
    else if(Node->GetObj().isNULL())
      SubNode_List->Push_Front(Node);
    else
      Attr_List->Push_Front(Node);
  }

public:
  CTxt_attrComposite_Export()
    :cxxlObject(Spirit_Easy),
     SubNode_List(new cxxlList<COMPOSITETXTDATA >,this),
     Attr_List(new cxxlList<COMPOSITETXTDATA >,this)
  {
  }

  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > cxxlFASTCALL GetSubNode_List()
  {
    return SubNode_List;
  }

  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > cxxlFASTCALL GetAttr_List()
  {
    return Attr_List;
  }
};


/********************************
**  class TxtSaveFilter
********************************/

/*
** 負責將被儲存體(cxxlPreserve)要保存的資料存起來
*/
class TxtSaveFilter:public SaveFilter
{
  COMPOSITETXTDATA *m_pTxtComposite;
  Smart_Ptr<cxxlList<TxtSaveFilter> > SubSaveFilter_List; // 記錄要可被 toSave() 叫用的子 TxtSaveFilter

  cxxlPreserve *_pPreserve;

  template <typename T>
  void cxxlFASTCALL _Save(T *Src, size_t Count, const UNICODE_String &Name)
  {
    wstringstream wss_DataCount;
    wstringstream wss_Data;
    wss_DataCount << Count;

    for(size_t i = 0; i < Count; ++i)
    {
      long tmp = Src[i];
      wss_Data << tmp;
      if(i < Count-1)
        wss_Data << ' ';
    }

    UNICODE_String DataCount_WString(wss_DataCount.str().c_str(), GetSpirit());
    UNICODE_String Data_WString(wss_Data.str().c_str(), GetSpirit());

    m_pTxtComposite->Add(DataCount_WString, Name+L"-Count");
    m_pTxtComposite->Add(Data_WString, Name);
  }

  // 繼承自 class Filter
  virtual bool cxxlFASTCALL Ref(const bool *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const char *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const short *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const int *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const long *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const wchar_t *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned char *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned short *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned int *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned long *Src, size_t Count, const UNICODE_String &Name)
  {
    _Save(Src, Count, Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const float *Src, size_t Count, const UNICODE_String &Name)
  {
    wstringstream wss_DataCount;
    wstringstream wss_Data;
    wss_DataCount << Count;

    for(size_t i = 0; i < Count; ++i)
    {
      wss_Data << Src[i];
      if(i < Count-1)
        wss_Data << ' ';
    }

    UNICODE_String DataCount_WString(wss_DataCount.str().c_str(), GetSpirit());
    UNICODE_String Data_WString(wss_Data.str().c_str(), GetSpirit());

    m_pTxtComposite->Add(DataCount_WString, Name+L"-Count");
    m_pTxtComposite->Add(Data_WString, Name);

    return true;
  }
  virtual bool cxxlFASTCALL Ref(const double *Src, size_t Count, const UNICODE_String &Name)
  {
    wstringstream wss_DataCount;
    wstringstream wss_Data;
    wss_DataCount << Count;

    for(size_t i = 0; i < Count; ++i)
    {
      wss_Data << Src[i];
      if(i < Count-1)
        wss_Data << ' ';
    }

    UNICODE_String DataCount_WString(wss_DataCount.str().c_str(), GetSpirit());
    UNICODE_String Data_WString(wss_Data.str().c_str(), GetSpirit());

    m_pTxtComposite->Add(DataCount_WString, Name+L"-Count");
    m_pTxtComposite->Add(Data_WString, Name);
    return true;
  }



public:
  // Constructor
  TxtSaveFilter(
    COMPOSITETXTDATA *pTxtComposite,
    cxxlPreserve *pPreserve,
    ISpirit *spirit )
    :cxxlObject(spirit),SaveFilter(spirit),SubSaveFilter_List(new cxxlList<TxtSaveFilter>(spirit),this)
  {
    _pPreserve = pPreserve;

    if(pPreserve == NULL)
      return;

    Lock(pPreserve);
    m_pTxtComposite = pTxtComposite;

    if(GetTransaction(pPreserve) == 0)
    {
      SetTransaction(pPreserve,1);

      for(const _Sets *p = Get_Sets_List(pPreserve);
          p != NULL;
          p = Next_Sets(p))
      {
        Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = GetPreserveList(p);

        unsigned long SubPreserveCount = cxxlPreserve_List->GetCount();

        wstringstream wsoutSubPreserveCount;

        wsoutSubPreserveCount << SubPreserveCount;
        UNICODE_String SubPreserveCount_WString(wsoutSubPreserveCount.str().c_str());
        pTxtComposite->Add(SubPreserveCount_WString, SETCOUNT);

        if(SubPreserveCount == 0)
          continue;

        cxxlPreserve_List->ResetPT(toHead);
        unsigned long i = 0;
        for(Smart_Ptr<cxxlPreserve> cxxlPreserve_Ptr = (*cxxlPreserve_List)++; i < SubPreserveCount; cxxlPreserve_Ptr = (*cxxlPreserve_List)++, ++i)
        {
          TxtSaveFilter *SF = new TxtSaveFilter(pTxtComposite->Add(NULL,GetName(p)), cxxlPreserve_Ptr, spirit);
          SubSaveFilter_List->Push_Back(SF);
        }
      }
    }

  }

  // Destructor
  virtual ~TxtSaveFilter()
  {
    if(_pPreserve != NULL)
    {
      SetTransaction(_pPreserve,0);
      SaveFilter::UnLock(_pPreserve);
    }
  }

  bool cxxlFASTCALL toSave()
  {
    if(_pPreserve == NULL)
      return true;

    if(GetTransaction(_pPreserve) == 1)
    {
      SaveFilter::SetTransaction(_pPreserve,0); // 同一個 Preserve 不會再被做一次

      // Smart_Ptr<cxxlList<COMPOSITETXTDATA > > SubTxtComposite_List = m_pTxtComposite->cxxlList_Create();
      SubSaveFilter_List->ResetPT(CxxlMan::toHead);
      for(Smart_Ptr<TxtSaveFilter> SubSaveFilter_Ptr = (*SubSaveFilter_List)++;
          !SubSaveFilter_Ptr.isNULL();
          SubSaveFilter_Ptr = (*SubSaveFilter_List)++ )
      {
        if(!SubSaveFilter_Ptr->toSave())
          return false;
      }

    }

    if(SaveFilter::Save(_pPreserve))
      return true;
    else
      return false;

  }


};

/********************************
**  class TxtLoadFilter
********************************/

/*
** 負責取回被儲存體(cxxlPreserve)保存的資料
*/
class TxtLoadFilter:public CxxlMan::LoadFilter
{
  // 為了傳遞進到 AutoDel_List
  class _Ptr
  {
    char *ptr;
    size_t Count;
  public:
    _Ptr(char *p, size_t count)
    {
      ptr = p;
      Count = count;
    }

    _Ptr(const _Ptr &Src)
    {
      ptr = Src.ptr;
      Count = Src.Count;
      ((_Ptr &)Src).ptr = NULL;
    }

    ~_Ptr()
    {
      delete [] ptr;
    }

    char *GetData()
    {
      return ptr;
    }

    size_t GetCount()
    {
      return Count;
    }
  };

protected:
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > SubTxtComposite_List;
  bool isCommit;
  list<_Ptr> AutoDel_List;
  list<_Ptr>::iterator it;

private:


  template<typename T>
  bool cxxlFASTCALL _Load(T *v, size_t Count, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      T *data = (T *)it->GetData();
      size_t count = it->GetCount();

      for(size_t i = 0; i < count; ++i)
        v[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {

      size_t count;
      char *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;
      if(//count != 0 &&// 儲存的永續資料設為 0 可無修件過關
        Count != count)
        return false;

      data = new char[count * sizeof(T)];

      AutoDel_List.push_back(_Ptr(data, count));

      for(size_t i = 0; i < count; ++i)
      {
        long temp;
        wss_Data >> temp;
        ((T *)data)[i] = (T)temp;
      }

      return true;
    }
    else
      return false;
  }


  // 繼承自 class Filter
  virtual bool cxxlFASTCALL Ref(const bool *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((bool *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const char *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((char *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const short *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((short *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const int *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((int *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const long *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((long *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const wchar_t *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((wchar_t *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned char *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned char *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned short *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned short *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned int *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned int *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned long *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned long *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const float *v, size_t Count,const UNICODE_String &Name)
  {
    if(isCommit)
    {
      float *data = (float *)it->GetData();
      size_t count = it->GetCount();

      for(size_t i = 0; i < count; ++i)
        ((float*)v)[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      size_t count;
      float *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;
      if(Count != count)
        return false;

      data = new float[count];

      AutoDel_List.push_back(_Ptr((char*)data, count));

      for(size_t i = 0; i < count; ++i)
      {
        wss_Data >> data[i];
      }

      return true;
    }
    else
      return false;
  }
  virtual bool cxxlFASTCALL Ref(const double *v, size_t Count,const UNICODE_String &Name)
  {
    if(isCommit)
    {
      double *data = (double *)it->GetData();
      size_t count = it->GetCount();

      for(size_t i = 0; i < count; ++i)
        ((double*)v)[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      size_t count;
      double *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;
      if(Count != count)
        return false;

      data = new double[count];

      AutoDel_List.push_back(_Ptr((char*)data, count));

      for(size_t i = 0; i < count; ++i)
      {
        wss_Data >> data[i];
      }

      return true;
    }
    else
      return false;
  }


  template<typename T>
  bool cxxlFASTCALL _LoadChk(T **v, size_t *Count,const UNICODE_String &Name)
  {
    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;

    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> *Count;
      *v = (T *)(new char[*Count * sizeof(T)]);

      AutoDel_List.push_back(_Ptr((char *)*v, *Count));

      for(size_t i = 0; i < *Count; ++i)
      {
        long temp;
        wss_Data >> temp;
        (*v)[i] = (T)temp;
      }

      return true;
    }
    else
      return false;
  }


  // 繼承自 class LoadFilter
  virtual bool cxxlFASTCALL LoadChk(const bool **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((bool **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const char **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((char **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const short **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((short **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const int **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((int **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const long **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((long **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const wchar_t **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((wchar_t **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned char **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((unsigned char **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned short **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((unsigned short **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned int **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((unsigned int **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned long **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk((unsigned long **)v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const float **v, size_t *Count,const UNICODE_String &Name)
  {
    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;

    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> *Count;
      *v = (float *)(new char[*Count * sizeof(**v)]);

      AutoDel_List.push_back(_Ptr((char *)*v, *Count));

      for(size_t i = 0; i < *Count; ++i)
      {
        wss_Data >> (*(float **)v)[i];
      }

      return true;
    }
    else
      return false;
  }
  virtual bool cxxlFASTCALL LoadChk(const double **v, size_t *Count,const UNICODE_String &Name)
  {
    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;

    UNICODE_String DataCountName = Name+L"-Count";
    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> *Count;
      *v = (double *)(new char[*Count * sizeof(**v)]);

      AutoDel_List.push_back(_Ptr((char *)*v, *Count));

      for(size_t i = 0; i < *Count; ++i)
      {
        wss_Data >> (*(double **)v)[i];
      }

      return true;
    }
    else
      return false;
  }

  template<typename T>
  bool cxxlFASTCALL _LoadRef(T *v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      T *data = (T *)it->GetData();
      size_t count = it->GetCount();

      for(size_t i = 0; i < count; ++i)
        v[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {

      size_t count;
      char *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;

      data = new char[count * sizeof(T)];

      AutoDel_List.push_back(_Ptr(data, count));

      for(size_t i = 0; i < count; ++i)
      {
        long temp;
        wss_Data >> temp;
        ((T *)data)[i] = (T)temp;
      }

      return true;
    }
    else
      return false;
  }


  // 繼承自 class LoadFilter
  virtual bool cxxlFASTCALL LoadRef(const bool **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new bool[it->GetCount()];
    }

    return _LoadRef((bool *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const char **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new char[it->GetCount()];
    }

    return _LoadRef((char *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const short **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new short[it->GetCount()];
    }

    return _LoadRef((char *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const int **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new int[it->GetCount()];
    }

    return _LoadRef((int *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const long **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new long[it->GetCount()];
    }

    return _LoadRef((long *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const wchar_t **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new wchar_t[it->GetCount()];
    }

    return _LoadRef((wchar_t *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned char **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new unsigned char[it->GetCount()];
    }

    return _LoadRef((unsigned char *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned short **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new unsigned short[it->GetCount()];
    }

    return _LoadRef((unsigned short *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned int **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new unsigned int[it->GetCount()];
    }

    return _LoadRef((unsigned int *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned long **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      delete [] *v;
      *v = new unsigned long[it->GetCount()];
    }

    return _LoadRef((unsigned long *)*v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const float **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      float *data = (float *)it->GetData();
      size_t count = it->GetCount();

      delete [] *v;
      *v = new float[count];

      for(size_t i = 0; i < count; ++i)
        ((float *)(*v))[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      size_t count;
      float *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;

      data = new float[count];

      AutoDel_List.push_back(_Ptr((char*)data, count));

      for(size_t i = 0; i < count; ++i)
      {
        wss_Data >> data[i];
      }

      return true;
    }
    else
      return false;
  }

  virtual bool cxxlFASTCALL LoadRef(const double **v, const UNICODE_String &Name)
  {
    if(isCommit)
    {
      double *data = (double *)it->GetData();
      size_t count = it->GetCount();

      delete [] *v;
      *v = new double[count];

      for(size_t i = 0; i < count; ++i)
        ((double *)(*v))[i] = data[i];

      it++;
      return true;
    }

    Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>, false> > SubTxtComposite_Ptr = (*SubTxtComposite_List)++;
    UNICODE_String DataCountName = Name+L"-Count";

    if(!SubTxtComposite_Ptr.isNULL() && SubTxtComposite_Ptr->GetName() == DataCountName)
    {
      size_t count;
      double *data;

      UNICODE_String DataCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      UNICODE_String Data_WString = (string_wrapper<wchar_t> *)((*SubTxtComposite_List)++)->GetObj();

      wstringstream wss_DataCount((const wchar_t*)DataCount_WString);
      wstringstream wss_Data((const wchar_t*)Data_WString);

      wss_DataCount >> count;

      data = new double[count];

      AutoDel_List.push_back(_Ptr((char*)data, count));

      for(size_t i = 0; i < count; ++i)
      {
        wss_Data >> data[i];
      }

      return true;
    }
    else
      return false;
  }

  virtual bool isChk() const
  {
    return isCommit != true;
  }


public:

  // Constructor
  TxtLoadFilter(
    const Smart_Ptr<cxxlList<COMPOSITETXTDATA > > &SubTxtComposite_Arg,
    ISpirit *spirit )
    :cxxlObject(spirit),
     LoadFilter(spirit),
     SubTxtComposite_List(SubTxtComposite_Arg,this)
  {

  }

  // Destructor
  virtual ~TxtLoadFilter()
  {
  }

};

/*
** class TxtStorage 叫用的
*/
class TxtLoadFilterForPreserveLoad:public TxtLoadFilter
{
  Smart_Ptr<cxxlList<TxtLoadFilterForPreserveLoad> > SubLoadFilter_List; // 記錄要可被 toLoad() 叫用的子 TxtLoadFilter
  cxxlPreserve *_pPreserve;

  bool OK;

public:
  TxtLoadFilterForPreserveLoad(
    COMPOSITETXTDATA *pTxtComposite,
    cxxlPreserve *pPreserve,
    ISpirit *spirit )
    :cxxlObject(spirit),
     TxtLoadFilter(pTxtComposite->cxxlList_Create(),spirit),
     SubLoadFilter_List(new cxxlList<TxtLoadFilterForPreserveLoad>(spirit),this)
  {
    isCommit = false;
    OK = true;
    _pPreserve = pPreserve;

    if(pPreserve == NULL)
    {
      if(pTxtComposite->GetCount() != 0)
        OK = false;

      return;
    }


    Lock(pPreserve);

    if(GetTransaction(pPreserve) == 0)
    {
      SetTransaction(pPreserve,1);

      SubTxtComposite_List->ResetPT(CxxlMan::toHead);

      for(const _Sets *p = Get_Sets_List(pPreserve);
          p != NULL;
          p = Next_Sets(p))
      {

        Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = SubTxtComposite_List->Pop_Front();

        if(SubTxtComposite_Ptr->GetName() != SETCOUNT)
        {
          OK = false;
          break;
        }

        unsigned long SetCount;

        UNICODE_String SetCount_WString = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
        wstringstream wsin_SetCount((const wchar_t*)SetCount_WString);
        wsin_SetCount >> SetCount;

        Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = GetPreserveList(p);
        unsigned long SubPreserveCount = cxxlPreserve_List->GetCount();
        if(SetCount != SubPreserveCount)
        {
          OK = false;
          break;
        }

        if(SubPreserveCount == 0)
          continue;

        cxxlPreserve_List->ResetPT(toHead);
        unsigned long i = 0;
        for(Smart_Ptr<cxxlPreserve> cxxlPreserve_Ptr = (*cxxlPreserve_List)++; i < SubPreserveCount; cxxlPreserve_Ptr = (*cxxlPreserve_List)++, ++i)
        {
          TxtLoadFilterForPreserveLoad *pTxtLoadFilter = new TxtLoadFilterForPreserveLoad(SubTxtComposite_List->Pop_Front(), cxxlPreserve_Ptr, spirit);
          if(pTxtLoadFilter->isOK() == false)
          {
            delete pTxtLoadFilter;
            OK = false;
            return;
          }
          else
            SubLoadFilter_List->Push_Back(pTxtLoadFilter);
        }
      }
    }
  }

  virtual ~TxtLoadFilterForPreserveLoad()
  {
    if(_pPreserve != NULL)
    {
      SetTransaction(_pPreserve,0);
      LoadFilter::UnLock(_pPreserve);
      _pPreserve = NULL;
    }
  }

  bool cxxlFASTCALL toLoad()
  {
    if(_pPreserve == NULL)
      return true;

    if(GetTransaction(_pPreserve) == 1)
    {
      SetTransaction(_pPreserve,2);

      SubTxtComposite_List->ResetPT(CxxlMan::toHead);
      SubLoadFilter_List->ResetPT(CxxlMan::toHead);
      for(Smart_Ptr<TxtLoadFilterForPreserveLoad> SubLoadFilter_Ptr = (*SubLoadFilter_List)++;
          !SubLoadFilter_Ptr.isNULL();
          SubLoadFilter_Ptr = (*SubLoadFilter_List)++)
      {
        if(SubLoadFilter_Ptr->toLoad() == false)
          return false;
      }

      return LoadFilter::Load(_pPreserve);
    }

    return true;
  }

  void cxxlFASTCALL toCommit(bool r)
  {
    if(_pPreserve == NULL)
      return;

    if(GetTransaction(_pPreserve) != 0)
    {
      if(GetTransaction(_pPreserve) == 2)
      {
        SetTransaction(_pPreserve, 0);

        SubLoadFilter_List->ResetPT(CxxlMan::toHead);
        for(Smart_Ptr<TxtLoadFilterForPreserveLoad> SubLoadFilter_Ptr = (*SubLoadFilter_List)++;
            !SubLoadFilter_Ptr.isNULL();
            SubLoadFilter_Ptr = (*SubLoadFilter_List)++)
        {
          SubLoadFilter_Ptr->toCommit(r);
        }

        if(r)
        {
          isCommit = true;
          it = AutoDel_List.begin();
          LoadFilter::Commit(_pPreserve,true);
        }
        else
          LoadFilter::Commit(_pPreserve,false);
      }
      else
        SetTransaction(_pPreserve, 0);

      LoadFilter::UnLock(_pPreserve);
      _pPreserve = NULL;
    }
  }

  bool cxxlFASTCALL isOK()
  {
    return OK;
  }

};

/*
** class Preserve2TxtStorage 叫用的
*/
class TxtLoadFilterForPreserve2Regenera:public TxtLoadFilter
{
public:
  TxtLoadFilterForPreserve2Regenera(
    const Smart_Ptr<cxxlList<COMPOSITETXTDATA > > &SubTxtComposite_Arg,
    ISpirit *spirit )
    :cxxlObject(spirit),
     TxtLoadFilter(SubTxtComposite_Arg,spirit)
  {
  }

  virtual ~TxtLoadFilterForPreserve2Regenera()
  {
  }

  bool cxxlFASTCALL toLoad(cxxlPreserve *pPreserve)
  {
    isCommit = false;
    SubTxtComposite_List->ResetPT(CxxlMan::toHead);
    return LoadFilter::Load(pPreserve);
  }

  void cxxlFASTCALL toCommit(cxxlPreserve *pPreserve, bool r)
  {
    isCommit = true;
//    SubTxtComposite_List->ResetPT(CxxlMan::toHead);
    it = AutoDel_List.begin();
    LoadFilter::Commit(pPreserve,r);
  }

};


/********************************
**  class Preserve2TxtStorage
********************************/

class Preserve2TxtStorage:public IPreserve2Storage
{
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > SubNode_List;
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Attr_List;

  UNICODE_String Name;
  UNICODE_String InterfaceID;
  UNICODE_String ClassID;
  UNICODE_String ObjID;
  UNICODE_String Group;
  UNICODE_String Spirit;

public:
  Preserve2TxtStorage(
    const Smart_Ptr<cxxlList<COMPOSITETXTDATA > > &SubNode_Arg,
    const Smart_Ptr<cxxlList<COMPOSITETXTDATA > > &Attr_Arg,
    const UNICODE_String &Name_Arg,
    const UNICODE_String &InterfaceID_Arg,
    const UNICODE_String &ClassID_Arg,
    const UNICODE_String &ObjID_Arg,
    const UNICODE_String &Group_Arg,
    const UNICODE_String &Spirit_Arg,
    ISpirit *spirit)
    :cxxlObject(spirit),
     SubNode_List(SubNode_Arg),
     Attr_List(Attr_Arg),
     Name(Name_Arg),
     InterfaceID(InterfaceID_Arg),
     ClassID(ClassID_Arg),
     ObjID(ObjID_Arg),
     Group(Group_Arg),
     Spirit(Spirit_Arg)
  {
  }
  virtual ~Preserve2TxtStorage()
  {

  }

  UNICODE_String cxxlFASTCALL GetName() const
  {
    return Name;
  }
  UNICODE_String cxxlFASTCALL GetInterfaceID() const
  {
    return InterfaceID;
  }
  UNICODE_String cxxlFASTCALL GetClassID() const
  {
    return ClassID;
  }
  UNICODE_String cxxlFASTCALL GetObjID() const
  {
    return ObjID;
  }
  UNICODE_String cxxlFASTCALL GetGroup() const
  {
    return Group;
  }
  UNICODE_String cxxlFASTCALL GetSpiritStr() const
  {
    return Spirit;
  }

  virtual bool isEmpty() const                         // 是空資料嗎(無子節點也無內容)
  {
    return SubNode_List->GetCount() == 0 && Attr_List->GetCount() == 0;
  }

  void ResetFirst() const                // 重置子節點序列至第一個位置
  {
    SubNode_List->ResetPT(toHead);
  }

  bool haveSetCount() const              // 檢查還有沒有子節點子集
  {
    Smart_Ptr<COMPOSITETXTDATA > SubNode_Ptr = SubNode_List->GetObj();

    if(SubNode_Ptr.isNULL() || SubNode_Ptr->GetName() != SETCOUNT)
      return false;
    else
      return true;
  }

  unsigned long GetSetCount() const // 取得子節點子集數量
  {
    unsigned long SetCount;

    Smart_Ptr<COMPOSITETXTDATA > SubNode_Ptr = (*SubNode_List)++;

    UNICODE_String SetCount_WString = (string_wrapper<wchar_t> *)SubNode_Ptr->GetObj();
    wstringstream wsin_SetCount((const wchar_t*)SetCount_WString);

    wsin_SetCount >> SetCount;

    return SetCount;
  }


  Smart_Ptr<IPreserve2Storage> cxxlFASTCALL GetIPreserve2StorageNext() const
  {
    Smart_Ptr<COMPOSITETXTDATA > SubNode_Ptr = (*SubNode_List)++;
    if(SubNode_Ptr.isNULL())
      return NULL;

    Smart_Ptr<CTxt_attrComposite_Export> CTxt_attrComposite_Export_Ptr = new CTxt_attrComposite_Export;
    SubNode_Ptr->Export(CTxt_attrComposite_Export_Ptr);

    return new Preserve2TxtStorage(
                 CTxt_attrComposite_Export_Ptr->GetSubNode_List(),
                 CTxt_attrComposite_Export_Ptr->GetAttr_List(),
                 SubNode_Ptr->GetName(),
                 CV(SubNode_Ptr,INTERFACEIDNAME),
                 CV(SubNode_Ptr,CLASSIDNAME),
                 CV(SubNode_Ptr,OBJIDNAME),
                 CV(SubNode_Ptr,GROUPNAME),
                 CV(SubNode_Ptr,SPIRITNAME),
                 this->GetSpirit());
  }

  bool cxxlFASTCALL Load(const Smart_Ptr<cxxlPreserve> &v) const
  {
    TxtLoadFilterForPreserve2Regenera LF(Attr_List,this->GetSpirit());
    bool r = LF.toLoad(v);
    LF.toCommit(v,r);
    return r;
  }

  static UNICODE_String cxxlFASTCALL CV(const Smart_Ptr<COMPOSITETXTDATA > &Node_Ptr, const UNICODE_String &Name)
  {
    UNICODE_String data_src = (string_wrapper<wchar_t>*)Node_Ptr->GetObj(Name);
    if(data_src.isNULL())
      return UNICODE_String();

    UNICODE_String data_count = (string_wrapper<wchar_t>*)Node_Ptr->GetObj(Name+L"-Count");
    if(data_count.isNULL())
      return UNICODE_String();

    wstringstream wss_DataCount((const wchar_t*)data_count);
    wstringstream wss_Data((const wchar_t*)data_src);

    size_t count;
    char *data;

    wss_DataCount >> count;
    if(count == 0)
      return UNICODE_String();

    data = new char[count * sizeof(wchar_t)];

    for(size_t i = 0; i < count; ++i)
    {
      long temp;
      wss_Data >> temp;
      ((wchar_t*)data)[i] = (wchar_t)temp;
    }

    return (wchar_t*)data;
  }
};



/********************************
**  class TxtStorage
********************************/

// Constructor
CxxlMan::TxtStorage::TxtStorage(ISpirit *spirit)
  :cxxlObject(spirit), Txt_Composite_Ptr(new Txt_attrComposite(L"root",spirit),this)
{
}

bool cxxlFASTCALL CxxlMan::TxtStorage::toSave(cxxlPreserve *v,const UNICODE_String &Name)
{
  CriticalSecHandle AutoCSH(csObject);

  if(v == NULL || Txt_Composite_Ptr->GetComposite(Name).isNULL() == false)
    return false;

  Smart_Ptr<COMPOSITETXTDATA > TxtCompositeHost_Ptr = Txt_Composite_Ptr->Add(NULL, Name);
  if(TxtCompositeHost_Ptr.isNULL())
    return false;

  TxtSaveFilter SF(TxtCompositeHost_Ptr, v, GetSpirit());
  if(SF.toSave())
    return true;

  Txt_Composite_Ptr->Delete(TxtCompositeHost_Ptr);
  return false;

}

bool cxxlFASTCALL CxxlMan::TxtStorage::toLoad(cxxlPreserve *v,const UNICODE_String &Name)
{
  CriticalSecHandle AutoCSH(csObject);

  if(v != NULL)
  {
    Smart_Ptr<COMPOSITETXTDATA > TxtCompositeHost_Ptr = Txt_Composite_Ptr->GetComposite(Name);
    if(TxtCompositeHost_Ptr.isNULL() == false)
    {
      TxtLoadFilterForPreserveLoad LF(TxtCompositeHost_Ptr, v, GetSpirit());
      if(LF.isOK())
      {
        bool r = LF.toLoad();
        LF.toCommit(r);
        return r;
      }
    }
  }

  return false;
}


bool cxxlFASTCALL CxxlMan::TxtStorage::Delete(const UNICODE_String &Name)
{
  return Txt_Composite_Ptr->Delete(Txt_Composite_Ptr->GetComposite(Name));
}

Smart_Ptr<IPreserve2Storage> cxxlFASTCALL CxxlMan::TxtStorage::GetIPreserve2Storage(const UNICODE_String &Name)
{
  Smart_Ptr<COMPOSITETXTDATA > TxtCompositeHost_Ptr = Txt_Composite_Ptr->GetComposite(Name);
  if(TxtCompositeHost_Ptr.isNULL())
    return NULL;

  Smart_Ptr<CTxt_attrComposite_Export> CTxt_attrComposite_Export_Ptr = new CTxt_attrComposite_Export;
  TxtCompositeHost_Ptr->Export(CTxt_attrComposite_Export_Ptr);

  return new Preserve2TxtStorage(
               CTxt_attrComposite_Export_Ptr->GetSubNode_List(),
               CTxt_attrComposite_Export_Ptr->GetAttr_List(),
               TxtCompositeHost_Ptr->GetName(),
               Preserve2TxtStorage::CV(TxtCompositeHost_Ptr,INTERFACEIDNAME),
               Preserve2TxtStorage::CV(TxtCompositeHost_Ptr,CLASSIDNAME),
               Preserve2TxtStorage::CV(TxtCompositeHost_Ptr,OBJIDNAME),
               Preserve2TxtStorage::CV(TxtCompositeHost_Ptr,GROUPNAME),
               Preserve2TxtStorage::CV(TxtCompositeHost_Ptr,SPIRITNAME),
               this->GetSpirit());
}

/************************************************************************/

CXXL_DLLEXPORT void cxxlFASTCALL
CxxlMan::TxtStorageExportTLC(std::wostream &wout, const Smart_Ptr<TxtStorage> &TxtStorage_Ptr)
{
  Smart_Ptr<COMPOSITETXTDATA > &Txt_Composite_Ptr = TxtStorage_Ptr->Txt_Composite_Ptr;

  NonUniqueTxtCompositeExport(wout, Txt_Composite_Ptr);
}

CXXL_DLLEXPORT Smart_Ptr<TxtStorage> cxxlFASTCALL
CxxlMan::TxtStorageImportTLC(std::wistream &win, ISpirit *spirit)
{
  Smart_Ptr<COMPOSITETXTDATA > tmpTxtComposite_Ptr = NonUniqueTxtCompositeImport(win, new cxxlComposite<string_wrapper<wchar_t>,false>(L"tempComposite", spirit));

  if(tmpTxtComposite_Ptr.isNULL())
    return NULL;

  TxtStorage *pTxtStorage = new TxtStorage(spirit);
  pTxtStorage->Txt_Composite_Ptr = tmpTxtComposite_Ptr;

  return pTxtStorage;
}

/***********************************************************************/

// TLC 規格的容器轉換到 XML 規格的容器
static void cxxlFASTCALL TLCtoXML(const Smart_Ptr<cxxlXml_Node> &XmlNode_Ptr,
                                  const Smart_Ptr<COMPOSITETXTDATA > &Txt_Composite_Ptr)
{
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Txt_Composite_Ptr_List =
    Txt_Composite_Ptr->cxxlList_Create();

  Txt_Composite_Ptr_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITETXTDATA > p = (*Txt_Composite_Ptr_List)++;
    p.isNULL() == false;
    p = (*Txt_Composite_Ptr_List)++)
  {
    Smart_Ptr<string_wrapper<wchar_t> > o = p->GetObj();
    if(o.isNULL())
    {
      Smart_Ptr<cxxlXml_Node> cxxlXml_Node_Ptr = XmlNode_Ptr->AddNode(p->GetName());
      TLCtoXML(cxxlXml_Node_Ptr,p);
    }
    else
    {
      Smart_Ptr<cxxlXml_Content> XmlContent_Ptr =
        XmlNode_Ptr->AddContent(p->GetName());
      XmlContent_Ptr->SetContent((string_wrapper<wchar_t> *)o);
    }
  }
}

// XML 規格的容器轉換到 TLC 規格的容器
static void cxxlFASTCALL XMLtoTLC(const Smart_Ptr<COMPOSITETXTDATA > &Txt_Composite_Ptr,
                                  const Smart_Ptr<cxxlXml_Node> &XmlNode_Ptr)
{
  Smart_Ptr<cxxlList<cxxlXmlComposite> > XmlComposite_List = XmlNode_Ptr->GetSubnodes();
  XmlComposite_List->ResetPT(toHead);

  for(Smart_Ptr<cxxlXmlComposite> p = (*XmlComposite_List)++;
      p.isNULL()  == false;
      p = (*XmlComposite_List)++)
  {
    Smart_Ptr<cxxlXml_Node> XmlNode_Ptr = p->ConvertToNode();
    if(XmlNode_Ptr.isNULL())
    {
      Smart_Ptr<cxxlXml_Content> XmlContent_Ptr =
        p->ConvertToContent();

      Txt_Composite_Ptr->Add(XmlContent_Ptr->GetContent(), XmlContent_Ptr->GetName());
    }
    else
    {
      Smart_Ptr<COMPOSITETXTDATA > TxtComposite_Ptr =
        Txt_Composite_Ptr->Add(NULL,XmlNode_Ptr->GetName());

      XMLtoTLC(TxtComposite_Ptr, XmlNode_Ptr);
    }
  }
}



CXXL_DLLEXPORT void cxxlFASTCALL
CxxlMan::TxtStorageExportXML(std::wostream &wout, const Smart_Ptr<TxtStorage> &TxtStorage_Ptr)
{
  Smart_Ptr<cxxlXml_Node> cxxlXml_Node_Ptr( new cxxlXml_Node(TxtStorage_Ptr->Txt_Composite_Ptr->GetName()) );
  TLCtoXML(cxxlXml_Node_Ptr, TxtStorage_Ptr->Txt_Composite_Ptr);

  ExportXML(wout, cxxlXml_Node_Ptr);
}

CXXL_DLLEXPORT Smart_Ptr<TxtStorage> cxxlFASTCALL
CxxlMan::TxtStorageImportXML(std::wistream &win, ISpirit *spirit)
{
  Smart_Ptr<cxxlXml_Node> XmlNode_Ptr = ImportXML(win, spirit);
  if(XmlNode_Ptr.isNULL())
    return NULL;

  Smart_Ptr<COMPOSITETXTDATA >
    TxtComposite_Ptr(new Txt_attrComposite(XmlNode_Ptr->GetName(), spirit));

  XMLtoTLC(TxtComposite_Ptr, XmlNode_Ptr);

  TxtStorage *pTxtStorage = new TxtStorage(spirit);

  pTxtStorage->Txt_Composite_Ptr = TxtComposite_Ptr;

  return pTxtStorage;
}


/************************************************************************************/

// 作為巡行記號
class Mark:public cxxlObject
{
  int Num; // 0 已退回，1 已進入， 2 重複進入
public:
  Mark()
    :cxxlObject(Spirit_Easy)
  {
    Num = 0;
  }

  int operator++()
  {
    return ++Num;
  }

  int operator--()
  {
    return --Num;
  }
};

// 以 preserve2 的 ObjID 為 Key 來記錄走過的次數
class ObjIDChk_Tree:public cxxlAVL_Tree<Mark, UNICODE_String, true>
{
  bool cxxlFASTCALL isLeftAt(UNICODE_String O_Key, UNICODE_String addKey) const
  {
    return O_Key <= addKey;
  }

  bool cxxlFASTCALL isEqual(UNICODE_String O_Key, UNICODE_String findKey)  const
  {
    return O_Key == findKey;
  }

public:
  ObjIDChk_Tree()
    :cxxlObject(Spirit_Easy)
  {}
};

// 收集各技節點，若 ClearObjID 為 true，順便檢查是否有循環參照
bool cxxlFASTCALL Collect(const Smart_Ptr<COMPOSITETXTDATA > &TxtComposite_Arg, const Smart_Ptr<cxxlList<COMPOSITETXTDATA > > &Collect_Arg, const Smart_Ptr<ObjIDChk_Tree> &ObjIDChk_Arg, bool ClearObjID)
{
  if(ClearObjID)
  {
    Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = TxtComposite_Arg->GetComposite(OBJIDNAME);
    if(SubTxtComposite_Ptr.isNULL() == false) // preserve2 的節點才須檢查
    {
      UNICODE_String Key = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      ObjIDChk_Arg->Add(new Mark, Key);
      Smart_Ptr<Mark> Mark_Ptr = ObjIDChk_Arg->GetObj(Key);
      int Num = ++(*Mark_Ptr);
      if(Num == 2) // 走過了
        return false;
    }
  }

  Collect_Arg->Push_Back(TxtComposite_Arg); // 把 preserve 或 preserve2 放入收集袋


  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Node_List = TxtComposite_Arg->cxxlList_Create();

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = (*Node_List)++;
    SubTxtComposite_Ptr.isNULL() == false;
    SubTxtComposite_Ptr = (*Node_List)++)
  {
    if(SubTxtComposite_Ptr->GetObj().isNULL()) // 是技節點
      if(Collect(SubTxtComposite_Ptr, Collect_Arg, ObjIDChk_Arg, ClearObjID) == false)
        return false;
  }

  if(ClearObjID)
  {
    Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = TxtComposite_Arg->GetComposite(OBJIDNAME);
    if(SubTxtComposite_Ptr.isNULL() == false)
    {
      UNICODE_String Key = (string_wrapper<wchar_t> *)SubTxtComposite_Ptr->GetObj();
      Smart_Ptr<Mark> Mark_Ptr = ObjIDChk_Arg->GetObj(Key);
      --(*Mark_Ptr); // 退回
    }
  }

  return true;
}

// 負責把 preserve2 的 ObjID 資料清掉
void cxxlFASTCALL DoClearObjID(const Smart_Ptr<COMPOSITETXTDATA > &COMPOSITETXTDATA_Arg)
{
  Smart_Ptr<COMPOSITETXTDATA > ObjIDNod_Ptr = COMPOSITETXTDATA_Arg->GetComposite(OBJIDNAME L"-Count");
  if(ObjIDNod_Ptr.isNULL())
    return;

  ObjIDNod_Ptr->SetObj(UNICODE_String(L"0"));

  ObjIDNod_Ptr = COMPOSITETXTDATA_Arg->GetComposite(OBJIDNAME);

  if(ObjIDNod_Ptr.isNULL() == false)
    ObjIDNod_Ptr->SetObj(UNICODE_String(L""));
}

// 負責把 preserve 的永存資料刪掉
void cxxlFASTCALL DoDelRestore(const Smart_Ptr<COMPOSITETXTDATA > &COMPOSITETXTDATA_Arg)
{
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Node_List = COMPOSITETXTDATA_Arg->cxxlList_Create();

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITETXTDATA > SubCOMPOSITETXTDATA_Ptr = (*Node_List)++;
    SubCOMPOSITETXTDATA_Ptr.isNULL() == false;
    SubCOMPOSITETXTDATA_Ptr = (*Node_List)++)
  {
    if(SubCOMPOSITETXTDATA_Ptr->GetObj().isNULL() == false)
    {
      // preserve2 的永存資料保留
      UNICODE_String Name = SubCOMPOSITETXTDATA_Ptr->GetName();

      if(Name == SETCOUNT)
        continue;

      if(Name == UNICODE_String(INTERFACEIDNAME) + L"-Count")
        continue;
      if(Name == INTERFACEIDNAME)
        continue;

      if(Name == UNICODE_String(CLASSIDNAME) + L"-Count")
        continue;
      if(Name == CLASSIDNAME)
        continue;

      if(Name == UNICODE_String(OBJIDNAME) + L"-Count")
        continue;
      if(Name == OBJIDNAME)
        continue;

      if(Name == UNICODE_String(GROUPNAME) + L"-Count")
        continue;
      if(Name == GROUPNAME)
        continue;

      if(Name == UNICODE_String(SPIRITNAME) + L"-Count")
        continue;
      if(Name == SPIRITNAME)
        continue;


      COMPOSITETXTDATA_Arg->Delete(SubCOMPOSITETXTDATA_Ptr);
    }
  }
}

// 切斷 cxxlPreserve2 的永存資料中共用物件的資訊，即讓 ObjID 資訊失去作用
bool cxxlFASTCALL CutPreserve2(const Smart_Ptr<TxtStorage> &TxtStorage_Arg, bool ClearObjID, bool DelRestore)
{
  Smart_Ptr<COMPOSITETXTDATA > TxtComposite_Ptr = TxtStorage_Arg->GetComposite();

  // 取得第一層所有物件永存資料的啟始節點
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Node_List = TxtComposite_Ptr->cxxlList_Create();

  // 準備存放所有物件永存資料的 List
  Smart_Ptr<cxxlList<cxxlList<COMPOSITETXTDATA > > > Collects_List = new cxxlList<cxxlList<COMPOSITETXTDATA > >;

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = (*Node_List)++;
    SubTxtComposite_Ptr.isNULL() == false;
    SubTxtComposite_Ptr = (*Node_List)++)
  {
    Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Collect_List = new cxxlList<COMPOSITETXTDATA >;
    Smart_Ptr<ObjIDChk_Tree> ObjIDChk_Ptr = new ObjIDChk_Tree;
    if(Collect(SubTxtComposite_Ptr, Collect_List, ObjIDChk_Ptr, ClearObjID) == false)
      return false;

    Collects_List->Push_Back(Collect_List);
  }

  Collects_List->ResetPT(toHead);
  for(Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Collect_List = (*Collects_List)++;
    Collect_List.isNULL() == false;
    Collect_List = (*Collects_List)++)
  {
    Collect_List->ResetPT(toHead);
    for(Smart_Ptr<COMPOSITETXTDATA > COMPOSITETXTDATA_Ptr = (*Collect_List)++;
      COMPOSITETXTDATA_Ptr.isNULL() == false;
      COMPOSITETXTDATA_Ptr = (*Collect_List)++)
    {
      if(ClearObjID)
        DoClearObjID(COMPOSITETXTDATA_Ptr);

      if(DelRestore)
        DoDelRestore(COMPOSITETXTDATA_Ptr);
    }
  }

  return true;
}

// 切斷 cxxlPreserve2 的永存資料中共用物件的資訊，即讓 ObjID 資訊失去作用
bool cxxlFASTCALL CutPreserve2(const Smart_Ptr<TxtStorage> &TxtStorage_Arg, const UNICODE_String &Name, bool ClearObjID, bool DelRestore)
{
  Smart_Ptr<COMPOSITETXTDATA > TxtComposite_Ptr = TxtStorage_Arg->GetComposite();

  // 只取指定名稱的物件永存資料的啟始節點
  Smart_Ptr<COMPOSITETXTDATA > SubTxtComposite_Ptr = TxtComposite_Ptr->GetComposite(Name);

  if(SubTxtComposite_Ptr.isNULL())
    return true; // 指定名稱的節點不存仍回覆 true

  // 準備存放指定物件永存資料節點的 List
  Smart_Ptr<cxxlList<COMPOSITETXTDATA > > Collect_List = new cxxlList<COMPOSITETXTDATA >;

  Smart_Ptr<ObjIDChk_Tree> ObjIDChk_Ptr = new ObjIDChk_Tree;
  if(Collect(SubTxtComposite_Ptr, Collect_List, ObjIDChk_Ptr, ClearObjID) == false)
    return false;

  Collect_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITETXTDATA > COMPOSITETXTDATA_Ptr = (*Collect_List)++;
    COMPOSITETXTDATA_Ptr.isNULL() == false;
    COMPOSITETXTDATA_Ptr = (*Collect_List)++)
  {
    if(ClearObjID)
      DoClearObjID(COMPOSITETXTDATA_Ptr);

    if(DelRestore)
      DoDelRestore(COMPOSITETXTDATA_Ptr);
  }

  return true;
}
